<?php
/**
* 이미지 업로드
*
* @author gudals
* @since 2011-12-05
* @ todo
*
* -------------------------------------------------------------------
* [사용 예]
* 	$utilImage = new utilImage();
* 	$sSection = 'product';
* 	$aResult = $utilImage->uploadArray($_FILES, $sSection);
*
*	[code] => 200
[result] => Array
(
[0] => product_20111206_13231435484998.jpg
)
*/

class utilImages
{
    // 파일서버 (service.inc.default.php)
    private $sFileServer = SC_FILE_SERVER;
    //private $sFileServer = 'dev-file.foodcam.co.kr';
    //private $sFileServer = '115.68.42.29';

    private $oFtp;
    //private $ftp_id = 'file';
    private $ftp_id = SC_FILE_SERVER_FTPID;
    //private $ftp_passwd = '#k@lf@hfflfrj@i!!';
    private $ftp_passwd = SC_FILE_SERVER_FTPPW;
    private $oFtpResult = false;

    // 서비스 섹션 구분 디렉토리
    private $sSection;

    private $sFileTmpName;

    // 파일 크기 (2M)
    private $iMaxSize = 10000000;

    // 썸네일 생성 여부
    private $bThumbnail = false;

    // 썸네일 사이즈
    private $iThumbWidth = 60;
    private $iThumbHeight = 60;
    private $iThumbName = 0;

    // 다중 썸네일 생성 여부
    private $bMultiThumbnail = false;

    // 다중 썸네일 사이즈
    private $aThumbSize = array();

    // 업로드 가능한 파일 확장자
    private $aFileExt = array('gif', 'jpg', 'png', 'jpeg');

    // 서비스 할 경우 : service
    // 개발할 때 : dev 로 변경
    //private $sUploadType = 'service';
    private $sUploadType = 'dev';

    private $sService = 'shavor';

    public function setService($sService)
    {
        if (empty($sService) === true) return false;

        $this->sService = $sService;
    }

    /**
     * 등록된 파일의 사이즈를 읽어온다.
     * @author replica50
     * @since 2013.07.02
     * @param string $sFile 파일위치 및 파일명 (ex. parent_2013_02_01_1230123123.jpg)
     * @return int
     */
    public function getFileSize($sFile)
    {
        if ($this->setFtpConnect() === false) {
            return 0;
        }

        $temp = explode('_', $sFile);
        $dir = $this->sService.'/'.$temp[0].'/'.$temp[1].'/'.$temp[2].'/'.$temp[3].'/'; // 위치 생성
        $chk_file = $dir.$sFile;

        $result = ftp_size($this->oFtp, $chk_file);

        // ftp 연결 종료
        if ($this->oFtp !== false) {
            ftp_close($this->oFtp);
            $this->oFtp = false;
        }

        if ($result != -1) {
            return $result;
        }
        return 0;
    }

    /**
    * ftp connect
    *
    * @return boolean
    */
    public function setFtpConnect()
    {
        // 파일 서버 ftp 접속
        if (!$this->oFtp) {
            $this->oFtp = ftp_connect($this->sFileServer);
            $this->oFtpResult = ftp_login($this->oFtp, $this->ftp_id, $this->ftp_passwd);
        }

        // passive mode 접속
        if (!ftp_pasv($this->oFtp, true)) {
            return false;
        }

        // ftp 접속 확인
        if (!$this->oFtpResult) {
            return false;
        }

        return true;
    }

    /**
    * ftp 디렉토리 생성
    *
    * @param string $sDirPath 디렉토리 경로
    * @return boolean
    */
    public function ftpMakeDir($sDirPath)
    {
        if (empty($sDirPath) === true) return false;

        $sSubDir = '';
        $aTmpDir = explode("/", $sDirPath);
        for ($i=0; $i<count($aTmpDir); $i++)
        {
            $_dir = $aTmpDir[$i];
            if (empty($_dir) === true) continue;

            if (!@ftp_chdir($this->oFtp, $_dir)) {
                ftp_mkdir($this->oFtp, $_dir);
                ftp_chmod($this->oFtp, 0755, $_dir);
                ftp_chdir($this->oFtp, $_dir);
            }
        }

        return true;
    }

    /**
     *
     * 파일 삭제
     * @param string $sFile 삭제할 파일 (ex: main/2012/08/01/main_th_2012_08_01.gif)
     * @return boolean
     */
    public function delete($sFile)
    {
        if (empty($sFile)) return false;

        // 파일 서버 ftp 접속
        // ftp 접속 확인
        if ($this->setFtpConnect() === false) {
            return false;
        }

        if (ftp_delete($this->oFtp, $sFile)) {
            $bResult = true;
        } else {
            $bResult = false;
        }

        // ftp 연결 종료
        if ($this->oFtp !== false) {
            ftp_close($this->oFtp);
            $this->oFtp = false;
        }

        return $bResult;
    }

    /**
    * 업로드 파일 크기 변경
    *
    * @param int $iMaxSize 파일 크드 (20000000)
    * @return boolean
    */
    public function setMaxSize($iMaxSize)
    {
        if (empty($iMaxSize) === true) return false;

        $this->iMaxSize = $iMaxSize;
    }

    /**
    * 썸네일 생성
    *
    * @param int $iWidth 넓이
    * @param int $iHeight 높이
    * @param boolean $bThumbnail 썸네일 생성 여부
    */
    public function setThumbnailMake($iWidth = 60, $iHeight = '', $bThumbnail = true)
    {
        if (empty($iWidth) === false) $this->iThumbWidth = $iWidth;
        //if (empty($iHeight) === false) $this->iThumbHeight = $iHeight;
        $this->iThumbHeight = $iHeight;

        $this->bThumbnail = $bThumbnail;

        // 다중 썸네일 생성 여부
        $this->bMultiThumbnail = false;
    }

    /**
     * 다중 썸네일 사이즈
     *
     * @param array $aThumbSize 다중 썸네일 사이즈 정보 $aThumbSize[0] = '60,100';
     * @return boolean
     */
    public function setMultiThumbnailMake ($aThumbSize)
    {
        if (empty($aThumbSize) === true) return false;

        $this->aThumbSize = $aThumbSize;

        // 다중 썸네일 생성 여부
        $this->bThumbnail = true;
        $this->bMultiThumbnail = true;
    }

    /**
     *
     * 파일 확장자 추가
     *
     * @param array $aFileExt 추가 할 확장자 정보
     * @return boolean
     */
    public function setFileExt($aFileExt)
    {
        if (empty($aFileExt)) return false;

        $this->aFileExt = array_merge($this->aFileExt, $aFileExt);
    }

    /**
    * 파일 확장자 (무조건 소문자로 리턴한다.)
    *
    * @param string $sFileName 파일 이름 (aaaa.jpg)
    */
    public function getFileExt($sFileName)
    {
        if (empty($sFileName) === true) return false;

        $aFile = explode(".", $sFileName);
        $iLen = count($aFile) - 1;
        $sFileExt = $aFile[$iLen];

        return strtolower($sFileExt);
    }

    /**
     *
     * 이미지 업로드
     *
     * @param array $aFiles 파일 업로드 정보
     * @param string $sSection 파일 업로드 디렉토리 정보
     * @return multitype:number string
     */
    public function uploadImage($aFiles, $sSection = 'temp')
    {
        return $this->upload($aFiles, $sSection);
    }
    
    /**
     *
     * 파일 EXIF 정보 read
     * @param stirng $sFile 파일명
     */
    public function readExif($sFile)
    {
        $aExif = exif_read_data($sFile, 0, true);
            
        if (empty($aExif) === false) {
            return array(200, $aExif['IFD0']);
        } else {
            return array(201, 'EXIF 정보가 없습니다.');
        }
    }
    
    /**
     * 
     * 이미지 회전
     * @param string $sFileName 파일명
     * @param int $iDegree 각도
     */
    public function imageRotate($sFileName, $iDegree)
    {
        $sSource = imagecreatefromjpeg($sFileName);
        $sRotate = imagerotate($sSource, $iDegree, 0);
        
        imagejpeg($sRotate, $sFileName);
        
        return $sFileName;
    }

    /**
    * 파일 업로드
    *
    * @param array $aFiles 파일 업로드 정보
    * @param string $sSection 파일 업로드 디렉토리 정보
    */
    public function upload($aFiles, $sSection = 'temp')
    {
        if (!is_array($aFiles) || empty($aFiles) === true) {
            return array(201, '정상적인 접속이 아닙니다.');
        }
        
        // 저장할 디렉토리 지정(서비스)
        $this->sSection = $sSection;
        
        // 이미지를 가져와서 파일 거시기 검사.
        // 이미지 EXIF 정보
        $aExif = $this->readExif($aFiles['tmp_name']);
        
        //echo '<pre>';
        //print_r($aExif);
        //exit;
        
        if (empty($aExif) === false) {
            // Orientation 정보에 의한 회전 각도
            if ($aExif[1]['Orientation'] == '8') {
                $iDegree = 90;
            } else if ($aExif[1]['Orientation'] == '3') {
                $iDegree = 180;
            } else if ($aExif[1]['Orientation'] == '6') {
                $iDegree = -90;
            }
            
            if ($aExif[0] == 200 && $aExif[1]['Orientation'] != 1) {
                $this->sFileTmpName = $this->imageRotate($aFiles['tmp_name'], $iDegree);
            } else {
                $this->sFileTmpName = $aFiles['tmp_name'];
            }
        } else {
            $this->sFileTmpName = $aFiles['tmp_name'];
        }
        
        $sFileName = $aFiles['name'];
        $iFileSize = $aFiles['size'];
        $sFileExt = $this->getFileExt($sFileName);

        // 파일 이름 확인
        if (empty($sFileName) === true) {
            return array(201, '정상적인 접속이 아닙니다.');
        }

        // 파일 사이즈 검사
        if ($iFileSize > $this->iMaxSize) {
            // 1M 이하 파일만 등록 가능합니다.
            return array(202, '파일 사이즈가 초과 되었습니다.');
        }

        // 파일 확장자 검사
        if (!in_array(strtolower($sFileExt), $this->aFileExt)) {
            // jpg, gif, png 파일만 등록 가능합니다.
            return array(203, '등록 가능한 파일 형식이 아닙니다.');
        }

        // 파일 서버 ftp 접속
        // ftp 접속 확인
        if ($this->setFtpConnect() === false) {
            return array(204, 'ftp connect error');
        }

        // 저장할 파일 이름(원본 파일)
        $aMctime = explode('.', microtime(true));
        //$sRealFileNameNotExt = date("Ymd").'_'.$this->iThumbWidth.'_'.$this->iThumbHeight.'_'.$aMctime[0].$aMctime[1];
        //$sRealFileNameNotExt = date("Y_m_d").'_'.$aMctime[0].$aMctime[1];

        // 파일 확장자에 따른 파일명 변경
        if (in_array($sFileExt, array('gif', 'jpg', 'png', 'jpeg'))) {
            $sRealFileNameNotExt = date("Y_m_d").'_'.$aMctime[0].$aMctime[1];
            $sRealFileName = $this->sSection.'_'.$sRealFileNameNotExt.'.'.$sFileExt;
        } else {
            $sRealFileNameNotExt = date("Y_m_d").'_'.$sFileName;
            $sRealFileName = $this->sSection.'_'.$sRealFileNameNotExt;
        }

        // 저장할 디렉토리 경로
        $sDirDate = date("Y").'/'.date("m").'/'.date("d");
        $sDirPath = '/'.$this->sService.'/'.$this->sSection.'/'.$sDirDate.'/';
        $this->ftpMakeDir($sDirPath);

        // 이미지 파일 업로드
        if (in_array(strtolower($sFileExt), array('jpg', 'jpeg', 'gif', 'png'))) {
            // 이미지 사이즈 검사
            // list($width, $height, $type, $attr) = getimagesize("img/flag.jpg");
            $aImgSize = getimagesize($this->sFileTmpName);
            $iWidth = $aImgSize[0];
            $iHeight = $aImgSize[1];

            // 다중 썸네일 생성
            if ($this->bMultiThumbnail === true) {
                if (empty($this->aThumbSize) === false) {
                    for ($i = 0, $iLen = count($this->aThumbSize); $i < $iLen; $i++) {
                        $aTmpSize = explode(',', $this->aThumbSize[$i]);

                        // 썸네일 사이즈 세팅
                        if($iWidth > $aTmpSize[0]) $this->iThumbName = "_".$aTmpSize[0];
                        else $this->iThumbName = "_".$iWidth;

                        $this->iThumbWidth  = $aTmpSize[0];
                        $this->iThumbHeight = $aTmpSize[1];

                        if (empty($this->iThumbWidth) === true) continue;

                        $aResult = $this->uploadImageOnce($sRealFileName, $sRealFileNameNotExt, $iWidth, $iHeight, $sFileExt, $i);
                        if ($aResult[0] != 200) continue;
                    }
                }

            } else {
                $aResult = $this->uploadImageOnce($sRealFileName, $sRealFileNameNotExt, $iWidth, $iHeight, $sFileExt);
                if ($aResult[0] != 200) return $aResult;
            }

          // 기타 파일 업로드
        } else {
            $sRealThumbFileName = '';
            if (!ftp_put($this->oFtp, $sRealFileName, $this->sFileTmpName, FTP_BINARY)) {
                return array(218, '파일 업로드 실패');
            }
        }

        // ftp 연결 종료
        if ($this->oFtp !== false) {
            ftp_close($this->oFtp);
            $this->oFtp = false;
        }

        //$sReturnFileName = (empty($sRealThumbFileName)) ? $sRealFileName : $sRealThumbFileName;
        $sRealFileName = $this->sSection.'_'.$sRealFileNameNotExt.$this->iThumbName.'.'.$sFileExt;
        return array(200, $sRealFileName);
    }
    
    /**
     * 썸네일 생성 요청
     *
     * @param string $sRealFileName 업로드 한 이미지
     * @param string $sRealFileNameNotExt 파일명
     * @param int $iWidth 업로드 한 이미지 넓이
     * @param int $iHeight 업로드 한 이미지 높이
     * @param string $sFileExt 확장자
     */
    private function uploadImageOnce ($sRealFileName, $sRealFileNameNotExt, $iWidth, $iHeight, $sFileExt, $is_upload = 0)
    {
        // 가로 사이즈 검사
        if ($iWidth >= $this->iThumbWidth && $this->bThumbnail === true) {

            // 썸네일 높이 값이 없을 경우 자동 생성
            if (empty($this->iThumbHeight) === true) {
                $this->iThumbHeight = ceil($this->iThumbWidth / $iWidth * $iHeight);
            }

            // 썸네일 파일 이름
            $sRealThumbFileName = $this->sSection.'_'.$sRealFileNameNotExt.'_'.$this->iThumbWidth.'.'.$sFileExt;

            if (substr(PHP_OS, 0, 3) == 'WIN') {
                $sSaveFileName = 'C:\Windows\Temp\\th_'.$sRealThumbFileName;
            } else {
                $sSaveFileName = SC_DIR_RESOURCE.'/thumbnail/temp/'.$sRealThumbFileName;
            }
            
            // 썸네일 생성
            $bResult = $this->makeThumbnailImage($this->sFileTmpName, $sSaveFileName);
            if ($bResult === false) {
                return array(205, '썸네일이 정상적으로 생성되지 않습니다.');
            }

            // 썸네일 이미지 전송
            if (!ftp_put($this->oFtp, $sRealThumbFileName, $sSaveFileName, FTP_BINARY)) {
                return array(206, '파일 업로드 실패');
            }
            
            // 썸네일 임시 파일삭제
            unlink($sSaveFileName);
            /*if(!$is_upload)
            {
                // 실제 이미지 전송
                if (!ftp_put($this->oFtp, $sRealFileName, $this->sFileTmpName, FTP_BINARY)) {
                    return array(207, '파일 업로드 실패');
                }
            }*/

        } else {
            //$sRealThumbFileName = '';
            $sRealThumbFileName = $this->sSection.'_'.$sRealFileNameNotExt.'_'.$iWidth.'.'.$sFileExt;
            if (!ftp_put($this->oFtp, $sRealThumbFileName, $this->sFileTmpName, FTP_BINARY)) {
                return array(208, '파일 업로드 실패');
            }
        }

        return array(200, $sRealThumbFileName);
    }

    /**
    * 썸네일 생성
    *
    *
    * @param string $sFileTmpName		원본이미지 경로 이름
    * @param string $sSaveFileName		저장될 이미지 경로 이름
    * @param int $iWidth				썸네일 세로
    * @param int $iHeight				썸네일 세로
    * @return boolean|unknown
    */
    public function makeThumbnailImage($sFileTmpName, $sSaveFileName)
    {
        if (empty($sFileTmpName) || empty($sSaveFileName)) return false;

        // 썸네일 파일로 이미지 복사
        if (!copy($sFileTmpName, $sSaveFileName)) {
            return false;
        }

        // 퍼미션 변경
        chmod($sSaveFileName, 0777);

        list($iWidth, $iHeight, $iImgType, $attr) = getimagesize($sFileTmpName);

        // 파일 사이즈 비율 계산
        //$iResizeWidth = ceil($this->iMaxWidth / $iWidth * $iWidth);
        //$iResizeHeight = ceil($this->iMaxWidth / $iWidth * $iHeight);
        $iResizeWidth = $this->iThumbWidth;
        if ($this->iThumbHeight) {
            $iResizeHeight = $this->iThumbHeight;
        } else {
            $iResizeHeight = ceil($this->iThumbWidth / $iWidth * $iHeight);
        }
        $oGd = gd_info();
        $sGdVer = substr(preg_replace("/[^0-9]/", "", $oGd['GD Version']), 0, 1);
        if (!$sGdVer) return false;

        // 이미지 확장자 (1:gif, 2:jgp, 3:png)
        if ($iImgType != 1 && $iImgType != 2 && $iImgType != 3) return false;

        // gif
        if ($iImgType == 1) {
            $imC = imagecreatefromgif($sFileTmpName);

            if ($sGdVer == 2) {
                $imS = imagecreatetruecolor($iResizeWidth, $iResizeHeight);
                imagecopyresampled($imS, $imC, 0, 0, 0, 0, $iResizeWidth, $iResizeHeight, $iWidth, $iHeight);
            } else {
                $imS = imagecreate($iResizeWidth, $iResizeHeight);
                imagecopyresized($imS, $imC, 0, 0, 0, 0, $iResizeWidth, $iResizeHeight, $iWidth, $iHeight);
            }

            //header('Content-Type: image/gif');

            imagegif($imS, $sSaveFileName, 100);

        // jpg
        } elseif ($iImgType == 2) {
            $imC = imagecreatefromjpeg($sFileTmpName);

            if ($sGdVer == 2) {
                $imS = imagecreatetruecolor($iResizeWidth, $iResizeHeight);
                imagecopyresampled($imS, $imC, 0, 0, 0, 0, $iResizeWidth, $iResizeHeight, $iWidth, $iHeight);
            } else {
                $imS = imagecreate($iResizeWidth, $iResizeHeight);
                imagecopyresized($imS, $imC, 0, 0, 0, 0, $iResizeWidth, $iResizeHeight, $iWidth, $iHeight);
            }

            //header('Content-Type: image/jpeg');

            imagejpeg($imS, $sSaveFileName, 100);

        // png
        } elseif ($iImgType == 3) {
            $imC = imagecreatefrompng($sFileTmpName);

            $imS = imagecreatetruecolor($iResizeWidth, $iResizeHeight);
            imagecopyresampled($imS, $imC, 0, 0, 0, 0, $iResizeWidth, $iResizeHeight, $iWidth, $iHeight);
            imagesavealpha($imS, true);

            /*
            if ($sGdVer == 2) {
                $imS = imagecreatetruecolor($iResizeWidth, $iResizeHeight);
                imagecopyresampled($imS, $imC, 0, 0, 0, 0, $iResizeWidth, $iResizeHeight, $iWidth, $iHeight);
            } else {
                $imS = imagecreate($iResizeWidth, $iResizeHeight);
                imagecopyresized($imS, $imC, 0, 0, 0, 0, $iResizeWidth, $iResizeHeight, $iWidth, $iHeight);
            }
            */

            /*
            $im = ImageCreateFromPNG($dirfile);
            imagealphablending($dst_img, false);
            imagecopyresampled($dst_img, $im, 0, 0, 0, 0, $new_w, $new_h, $width, $height);
            imagesavealpha($dst_img, true);
            imagePNG($dst_img, $thumbdirfile,0);
            */

            //header('Content-Type: image/png');

            imagepng($imS, $sSaveFileName, 0);
        }

        // 메모리에 있는 그림 삭제
        //imagedestroy($imS);

        return true;
    }

    /**
     *
     * 파일 전송
     * @param string $sSendFile 보내는 파일 경로
     * @param string $sReceiveFile 받는 파일 명
     * @param string $sSection 저장할 디렉토리
     * @return boolean
     */
    public function sendFile($sSendFile, $sReceiveFile, $sSection)
    {
        if (empty($sSendFile) || empty($sReceiveFile)) return false;

        // 파일 서버 ftp 접속
        // ftp 접속 확인
        if ($this->setFtpConnect() === false) {
            return array(201, 'ftp 접속이 정상적이지 않습니다.');
        }

        $this->ftpMakeDir($sSection);

        // 파일 전송
        if (!ftp_put($this->oFtp, $sReceiveFile, $sSendFile, FTP_BINARY)) {
            return array(202, '파일 업로드 실패');
        }

        return array(200, '파일 업로드 성공');
    }
}